from CoTec.core.database.BaseTableStructure import BaseTableStructure
from CoTec.core.database.BaseTableStructure import Record

from CoTec.core.exception.exception_go import *

from CoTec.core.database.GeneralDao import GeneralDao


class StructureGuard(object):
    """
    依据  DBStructure 检查数据库完整性
    """
    from enum import Enum
    class Errors(Enum):
        LakeValue = 1
        NoKey = 2
        Other = 3

    def __init__(self, conf):
        self.config = conf

    def check(self, list):
        """
        传入待检测表list
        :param list:
        :return:
        """
        log = []

        for table in list:
            records = table.all_key()

            try:
                table_name = table.TableName
                targets = self.check_exists(table_name, records)

                if len(targets) > 0:
                    log.append((table_name, targets))
            except TableStructureKeyLackException as e:
                return (self.Errors.LakeValue, '')
            except TableStructureNoKeyException as e:
                return (self.Errors.NoKey, e.args[0], e.args[1])
            # except Exception:
            #     return (self.Errors.Other, '')

        return log

    def check_exists(self, table, records:list):
        """
        简单存在检测
        :return:
        """
        keys = []
        types = []
        table_key = []

        targets = []

        for index,record in enumerate(records):
            tuple = self.unpack(record)

            if tuple is None:
                raise TableStructureKeyLackException(index)

            keys.append(tuple[0])
            types.append(tuple[1])

        table_key = keys.copy()

        while(True):
            if self.try_get(table, table_key, keys, types, targets) == 1:
                break

        return targets

    def try_get(self, table, table_key, keys, types, targets):
        dao = GeneralDao(self.config)

        try:
            limit = (0,1)
            res = dao.get(table, table_key, limit=limit)
        except Exception as e:
            tmp = e.args[1]

            if 'unknown column' in tmp.lower():
                key = tmp.split('\'', 2)
                key = key[1]
                type = types[keys.index(key)]

                table_key.remove(key)
                targets.append((key,type))

                dao.add_column(table, key, type)

            elif 'table' in tmp.lower() and 'exist' in tmp.lower():
                targets.append(('table', table))

                primary = self.primary_key_getter(table_key, types)

                dao.add_table(table,primary[0],primary[1])

            return 0

        return 1

    def primary_key_getter(self, keys:[], types:[]):
        try:
            if 'id' in keys:
                type = types[keys.index('id')]
                return ('id', type)
        except Exception:
                return ('id','VARCHAR(255)')

    def add_key(self, table, key, type):
        dao = GeneralDao(self.config)

        # try:

        # except Exception as e:
        #     raise

        pass

    def unpack(self, record):
        key = record.key
        type = record.type

        if key is None or key == '' or type is None or key == '':
            return None

        return (key, type)

    def check_relativity(self, list):
        """
        结构相关性检测
        :return:
        """
        pass

# list = [TBNews()]
#
# guard = StructureGuard()
# guard.check(list)





